import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:study_demo/api/api.dart';
import 'package:study_demo/api/bean.dart';
import 'package:study_demo/base/base_chess_controller.dart';
import 'package:study_demo/base/count_controller.dart';
import 'package:study_demo/ext/tile_ext.dart';
import 'package:study_demo/style/analysis_data_painter.dart';
import 'package:study_demo/util/other_platform_chess.dart';
import 'package:tile/tile.dart';

import '../../base/BaseController.dart';
import '../../base/situation_controller.dart';
import '../../generated/assets.dart';
import '../../util/commond.dart';
import '../../util/file.dart';
import '../../util/level.dart';

class AIController extends BaseChessController
    with WidgetsBindingObserver, OtherPlatformChessListener {
  final type = 1.obs;
  final level = 2.obs;
  final roleIndex = 0.obs;
  final result = ''.obs;
  final roles = <AIRole>[].obs;
  final roleList = <String>[].obs;
  final aiLevels = <AILevel>[].obs;
  final aiLevelList = <String>[].obs;
  final aiLevelIndex = 0.obs;
  final aiName = ''.obs;
  AIRole role = AIRole();
  AILevel aiLevel = AILevel();
  String levelInfo = '';

  TextEditingController _sgfEditingController = TextEditingController();

  TextEditingController get sgfEditingController => _sgfEditingController;

  TextEditingController _resultEditingController = TextEditingController();

  TextEditingController get resultEditingController => _resultEditingController;

  TextEditingController _numEditingController = TextEditingController();

  TextEditingController get numEditingController => _numEditingController;

  @override
  void onInit() {
    super.onInit();
    initRole();
  }

  initRole() async {
    var result = await loadAsset(Assets.fileAiRole);
    roles.value = List<AIRole>.from(
        json.decode(result).map((e) => AIRole.fromJson(e)).toList());
    roles.forEach((it) {
      roleList.add(it.name!);
    });
  }

  changeType(int aiType) {
    type.value = aiType;
    _resultEditingController.text = '';
  }

  importSgf() async {
    var sgf = await pickSgf();
    if (sgf != null) {
      print('sgf:$sgf');
      _sgfEditingController.text = sgf;
      board.showSgfGame(sgf, refreshUI: true);
    }
  }

  confirm() {
    var num = int.parse(_numEditingController.text.toString().trim());
    board.regret(board.getCount() - num, refreshUI: true);
  }

  transformFormat() {}

  @override
  boardChanged(BoardFrame frame, BoardChange boardChanged) {
    if (boardChanged.selfNewChess && boardChanged.addNum > 0) {
      print('boardChanged:${boardChanged.selfNewChess}');
      _aiStep();
    }
  }

  _aiStep() {
    var code = type.value == 1
        ? galaxy_ai
        : type.value == 2
            ? leena_ai
            : kata_ai;
    if (type.value == 4) {
      code = kata_lower_level;
    }
    var end = type.value == 2 ? '' : '#' + level.value.toString();
    if (type.value == 4) {
      end = levelInfo;
    }
    var info = board.getBoardSize().toString() + '#' + board.allStep + end;
    var requestModel = RequestModel(code, info);
    var portType = 0;
    if (type.value == 3) {
      portType = 4;
    } else if (type.value == 4) {
      portType = 7;
    }
    api
        .getAIStep(requestModel, type: portType, showLoadingUI: false)
        .then((value) {
      var response = value;
      print('value:$value');
      var responseModel = ResponseModel.fromJson(value.data);
      print('responseModel:$responseModel');
      if (responseModel.error == 0) {
        var data = responseModel.data;
        if (data is String) {
          ChessStep step = data.gtpToChessStep(board.nextColor,
              boardSize: board.getBoardSize());
          board.showXY(step.x, step.y, forceChess: true, refreshUI: true);
          _showInfo(requestModel, response.realUri, responseModel.data);
        }
      } else {
        toast(responseModel.msg!);
      }
    });
  }

  changeLevel(String value) {
    level.value = levels.toList().indexOf(value) + 2;
  }

  changeRole(String value) {
    roleIndex.value = roleList.indexOf(value);
    role = roles[roleIndex.value];
    aiLevels.value = roles[roleIndex.value].aiLevels!;
    aiLevelList.clear();
    aiLevels.forEach((it) {
      aiLevelList.add(it.name!);
    });
  }

  changeAiLevel(String value) {
    aiLevelIndex.value = aiLevelList.indexOf(value);
    aiLevel = aiLevels[aiLevelIndex.value];
    aiName.value = roles[roleIndex.value].desc! +
        '(' +
        aiLevels[aiLevelIndex.value].name! +
        ')';
    levelInfo =
        "#" + aiLevel.level.toString() + '#' + role.style.toString() + '#1';
    print('levelInfo:$levelInfo');
  }

  hotPhoto() {
    if (type.value == 1) {
      type.value = 2;
    }
    var code = type.value == 2 ? leena_hot_photo : kata_hot_photo;
    var end = type.value == 2 ? '#0' : '#1';
    var info = board.getBoardSize().toString() + '#' + board.allStep + end;
    var requestModel = RequestModel(code, info);
    var portType = 5;
    if (type.value == 3) {
      portType = 4;
    } else {
      if (board.getBoardSize() == 9) {
        portType = 2;
      } else if (board.getBoardSize() == 13) {
        portType = 3;
      }
    }

    api
        .getAIStep(requestModel, type: portType, showLoadingUI: false)
        .then((value) {
      var response = value;
      print('value:$value');
      var responseModel = ResponseModel.fromJson(value.data);
      print('responseModel:$responseModel');
      _showResult(
          requestModel, responseModel, response.realUri, responseModel.data);
    });
  }

  recommend() {
    if (type.value == 1) {
      type.value = 2;
    }
    var code = '';
    if (type.value == 3 || board.getBoardSize() < 19) {
      code = recommend_board_kata;
    } else {
      code = recommend_board_leena;
    }
    var info = board.getBoardSize().toString() + '#' + board.allStep + '#21';
    var requestModel = RequestModel(code, info);
    var portType = 5;
    if (type.value == 3) {
      portType = 4;
    } else {
      if (board.getBoardSize() == 9) {
        portType = 2;
      } else if (board.getBoardSize() == 13) {
        portType = 3;
      }
    }

    api
        .getAIStep(requestModel, type: portType, showLoadingUI: false)
        .then((value) {
      var response = value;
      print('value:$value');
      var responseModel = ResponseModel.fromJson(value.data);
      print('responseModel:$responseModel');
      _showResult(
          requestModel, responseModel, response.realUri, responseModel.data,
          type: 1);
    });
  }

  _showResult(RequestModel requestModel, ResponseModel responseModel, Uri uri,
      String data,
      {int type = 0}) {
    if (responseModel.error == 0) {
      var data = responseModel.data;
      if (data is String) {
        switch (data) {
          case "resign":
            toast('AI也拯救不了了');
            break;
          case "pass":
            toast('AI pass一手');
            break;
          default:
            var steps = data.split('#');
            var analysisPoints = <AnalysisPoint>[];
            for (var element in steps) {
              var split = element.split(':');
              var firstStep =
                  type == 0 ? split[1].split(' ')[0] : split[0].split(' ')[0];
              var analysisPoint = AnalysisPoint()
                ..x =
                    firstStep.gtpToPosition(boardSize: board.getBoardSize())![0]
                ..y =
                    firstStep.gtpToPosition(boardSize: board.getBoardSize())![1]
                ..winRate = double.parse(type == 0 ? split[0] : split[1])
                ..pv = '';
              analysisPoints.add(analysisPoint);
            }

            board.showAnalysisAINext(analysisPoints, refreshUI: true);
            break;
        }
        _showInfo(requestModel, uri, data);
      }
    } else {
      toast(responseModel.msg!);
    }
  }

  _showInfo(RequestModel requestModel, Uri uri, String data) {
    _resultEditingController.text = '请求信息:' +
        uri.toString() +
        '\n' +
        requestModel.toJson().toString() +
        '\n' +
        '返回结果:' +
        data;
  }

  regret() {
    board.clearFlag();
    board.regret(1, refreshUI: true);
  }

  count() {
    countByServer(board).then((value) {
      result.value = transformResult(value.result!, 0, false);
    });
  }

  situation() {
    getSituation(board).then((value) {
      result.value = value;
    });
  }

  @override
  onResponseFromOtherPlatform(String sgf) {
    print('sgf:$sgf');
    board.showSgfGame(sgf, refreshUI: true);
  }
}
